import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Poem } from './entities/poem.entity';
import { FindOptionsWhere, Repository } from 'typeorm';
import { CreateDto } from './dto/create.dto';
import { PoemTag } from '../poem-tags/entities/poem-tag.entity';
import { paginatedScrape } from 'src/common/utils/scrape';
import { scrapePoemId } from 'src/common/utils/scrape/poem';
import { batchScrapeUrls } from 'src/common/utils/scrape/poem-ext';
import { Poet } from '../poet/entities/poet.entity';
import { FindDto } from './dto/find.dto';
import { UpdateDto } from './dto/update.dto';
import { DeleteDto } from './dto/delete.dto';
import { ListDto } from './dto/list.dto';
@Injectable()
export class PoemService {
  @InjectRepository(Poem)
  private readonly poemRepository: Repository<Poem>;

  @InjectRepository(PoemTag)
  private readonly poemTagRepository: Repository<PoemTag>;

  @InjectRepository(Poet)
  private readonly poetRepository: Repository<Poet>;

  async create({ poetId, poemTagIds, ...poem }: CreateDto) {
    const isExist = await this.poemRepository.findOne({
      where: {
        title: poem.title,
        poet: { id: poetId },
      },
    });
    if (isExist) {
      throw new BadRequestException('该诗名称已存在');
    }
    const newPoem = this.poemRepository.create({
      ...poem,
      ...(poetId && { poet: { id: poetId } }),
    });

    if (poemTagIds && poemTagIds.length > 0) {
      const tags = await this.poemTagRepository.findByIds(poemTagIds);
      if (tags.length !== poemTagIds.length) {
        throw new BadRequestException('部分标签id不存在');
      }
      newPoem.poemTags = tags;
    }
    return await this.poemRepository.save(newPoem);
  }

  async update(updateDto: UpdateDto) {
    const { id, poetId, poemTagIds, ...poem } = updateDto;
    const poemToUpdate = await this.poemRepository.findOne({
      where: { id },
    });
    if (!poemToUpdate) {
      throw new BadRequestException('诗歌不存在');
    }
    if (poetId) {
      const poet = await this.poetRepository.findOne({
        where: { id: poetId },
      });
      if (!poet) {
        throw new BadRequestException('诗人不存在');
      }
      poemToUpdate.poet = poet;
    }
    if (poemTagIds) {
      const tags = await this.poemTagRepository.findByIds(poemTagIds);
      if (tags.length !== poemTagIds.length) {
        throw new BadRequestException('部分标签id不存在');
      }
      poemToUpdate.poemTags = tags;
    }
    Object.assign(poemToUpdate, poem);
    return await this.poemRepository.update(id, poemToUpdate);
  }

  async delete(deleteDto: DeleteDto) {
    const { id } = deleteDto;
    const poemToDelete = await this.poemRepository.findOne({
      where: { id },
    });
    if (!poemToDelete) {
      throw new BadRequestException('诗歌不存在');
    }
    return await this.poemRepository.delete(id);
  }

  async find(findDto: FindDto) {
    const { title, id } = findDto;
    const query: FindOptionsWhere<Poem> = {};
    if (title) {
      query.title = title;
    }
    if (id) {
      query.id = id;
    }
    const poem = await this.poemRepository.findOne({
      where: query,
      relations: ['poet', 'poemTags'],
    });
    return poem;
  }

  async list(listDto: ListDto) {
    const { page, limit, title, id, content } = listDto;
    const query: FindOptionsWhere<Poem> = {};
    if (title) {
      query.title = title;
    }
    if (id) {
      query.id = id;
    }
    if (content) {
      query.content = content;
    }
    const [poems, total] = await this.poemRepository.findAndCount({
      where: query,
      relations: ['poet', 'poemTags'],
      skip: (page - 1) * limit,
      take: limit,
    });
    return {
      list: poems,
      total,
      page,
      limit,
    };
  }

  // 爬取所有诗的id
  async crawl() {
    try {
      const filePath = 'src/scrape-data/poem-ids.txt';
      await paginatedScrape(
        scrapePoemId,
        'https://aspoem.com/zh-Hans/list',
        Math.ceil(25 / 12),
        // Math.ceil(1),
        filePath,
        500,
      );
      return '爬取成功';
    } catch (error) {
      throw new BadRequestException(error);
    }
  }

  async crawlContent() {
    return batchScrapeUrls(
      'src/scrape-data/poem-ids-fix.txt',
      'src/scrape-data/poem-content-fix.txt',
      500,
    );
  }

  // 处理好的数据入库
  async createPoemWithPoet(data: {
    title: string;
    content: string;
    translation: string;
    notes: object;
    author: string;
    dynasty: string;
    tagNames: string[];
  }) {
    // 1. 处理诗人
    let poet = await this.poetRepository.findOne({
      where: { name: data.author },
    });

    if (!poet) {
      poet = this.poetRepository.create({
        name: data.author,
        dynasty: data.dynasty,
      });
      await this.poetRepository.save(poet);
    }

    // 2. 检查诗歌是否已存在
    const isExist = await this.poemRepository.findOne({
      where: {
        title: data.title,
        poet: { id: poet.id },
      },
    });
    if (isExist) {
      throw new Error('该诗名称已存在');
    }

    // 3. 创建诗歌
    const newPoem = this.poemRepository.create({
      title: data.title,
      content: data.content,
      translate: data.translation,
      notes: data.notes ? JSON.stringify(data.notes) : null,
      poet: { id: poet.id },
    });

    // 4. 处理标签
    const tags = [];
    for (const tagName of data.tagNames) {
      let tag = await this.poemTagRepository.findOne({
        where: { name: tagName },
      });

      if (!tag) {
        tag = this.poemTagRepository.create({
          name: tagName,
        });
        await this.poemTagRepository.save(tag);
      }
      tags.push(tag);
    }

    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
    newPoem.poemTags = tags;
    return await this.poemRepository.save(newPoem);
  }
}
